/*
 * Copyright 2009 rashaguo <rashaguo@gmail.com>
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 */
#ifndef LOGGER_H
#define LOGGER_H

#include <string>
#include <fstream>

#ifdef CC_GCC
 #define __FUNCTION__ __PRETTY_FUNCTION__
#endif

#ifndef LOGGER_COMPONENT
 #define LOGGER_COMPONENT "OPNSS"
#endif

#define LOG_DEBUG Logger::getInstance()->getHelper(LOGGER_COMPONENT, Logger::Debug, __FUNCTION__, NULL, 0)
#define LOG_INFO  Logger::getInstance()->getHelper(LOGGER_COMPONENT, Logger::Info,  __FUNCTION__, NULL, 0)
#define LOG_WARN  Logger::getInstance()->getHelper(LOGGER_COMPONENT, Logger::Warn,  __FUNCTION__, NULL, 0)
#define LOG_ERROR Logger::getInstance()->getHelper(LOGGER_COMPONENT, Logger::Error, __FUNCTION__, NULL, 0)
#define LOG_FATAL Logger::getInstance()->getHelper(LOGGER_COMPONENT, Logger::Fatal, __FUNCTION__, __FILE__, __LINE__)

class QMutex;

class Logger
{
public:

    enum Level {
        Debug,
        Info,
        Warn,
        Error,
        Fatal
    };


    class Helper
    {
    public:

        Helper(const char* component, Level level, const char *className, const char* fileName, int line);

        void operator()(const std::string &message);

        void operator()(const char* format, ...);

    private:

        const char* m_component;

        Level m_level;

        const char* m_className;

        const char* m_fileName;

        int m_line;

    };

    void setLogFileName(const std::string &log_filename);

    std::string getLogFileName() const;

    static Logger* getInstance();

    ~Logger();

    Helper getHelper(const char* component, Logger::Level level, const char* className, const char* fileNmae, int line);

    void debug(const std::string &component, const std::string &className, const std::string &message);

    void info(const std::string &component, const std::string &className, const std::string &message);

    void warn(const std::string &component, const std::string &className, const std::string &message);

    void error(const std::string &component, const std::string &className, const std::string &message);

    void fatal(const std::string &component, const std::string &className, const std::string &message, const char* fileName, int line);

    void flush();

    void log(const std::string & component, Level level, const std::string &className,
                    const std::string & message, const char * fileName = NULL, int line = 0);


private:

    Logger();

    enum  LogFileState {

        LogFileState_Unset,
        LogFileState_Disabled,
        LogFileState_Defined,
        LogFileState_Created
    };

    LogFileState m_logFileState;

    std::string m_logFileName;

    std::ofstream m_file;

    static QMutex m_mutex;
};

#endif
